#include "fn_box.h"
// #include <map>
// #include <set>

FnBox::FnBox()
{
}

bool FnBox::setInterval(const char *name, uint32_t interval, std::function<void(const char *)> fn)
{
    auto now = micros();
    if (name == NULL || fn == NULL || interval == 0)
        return false;
    // if (hasName(name))
    //     return false;
    cb_map[name] = _my_callback_t{
        fn,
        interval,
        now,
        now + interval,
    };
    return true;
}

void FnBox::clearInterval(const char *name)
{
    if (name == NULL)
        return;
    cb_map.erase(name);
}

bool FnBox::hasName(const char *name)
{
    auto it = cb_map.find(name);
    return it != cb_map.end();
}

void FnBox::scan()
{
    for (auto it = cb_map.begin(); it != cb_map.end(); ++it)
    {
        auto now = micros();
        auto cb = it->second;
        // check overflow
        if (cb.next_micros < cb.interval && now <= UINT32_MAX)
        {
            continue;
        }
        if (now < cb.next_micros)
        {
            continue;
        }
        // fix rate
        it->second.last_micros = cb.next_micros;
        it->second.next_micros = cb.next_micros + cb.interval;
        // callback
        auto name = it->first;
        cb.fn(name);
    }
}

// FnBox::FnBox()
// {
//     for (fn_id_t i = 1; i < 17; i++)
//     {
//         id_set.insert(i);
//     }
// }
// void FnBox::clearInterval(fn_id_t id)
// {
//     // auto it = cb_map.find(id);
//     // if (it == cb_map.end())
//     // {
//     //     return;
//     // }
//     cb_map.erase(id);
//     id_set.insert(id);
// }

// fn_id_t FnBox::setInterval(std::function<void(fn_id_t)> fn, uint32_t interval)
// {
//     // get new id
//     auto it = id_set.begin();
//     if (it == id_set.end())
//     {
//         return 0;
//     }
//     auto id = *it;
//     id_set.erase(id);
//     cb_map[id] = _my_callback_t{
//         fn,
//         interval,
//     };
//     return id;
// }
// void FnBox::scan()
// {
//     for (auto it = cb_map.begin(); it != cb_map.end(); ++it)
//     {
//         auto cb = it->second;
//         auto id = it->first;
//         auto x = cb_emit_us_map.find(id);
//         auto now = micros();
//         if (x == cb_emit_us_map.end())
//         {
//             // first time callback
//             cb_emit_us_map[id] = now;
//             cb.fn(id);
//             continue;
//         }
//         // check duration
//         auto last_time = x->second;
//         // TODO: overflow
//         if (now - last_time < cb.interval)
//         {
//             continue;
//         }
//         // callback
//         cb_emit_us_map[id] = now;
//         cb.fn(id);
//     }
// }
